package com.weic.easycache.framework;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import android.app.Application;

import com.weic.easycache.framework.user.IUser;
import com.weic.easycache.framework.user.IUserConfig;
import com.weic.easycache.helper.SharedPrefHelper;
import com.weic.easycache.utils.CrashHandler;

@SuppressWarnings("unchecked")
public abstract class AbsApp extends Application {
	static {
		CrashHandler.startCaughtAllException(false, true);
	}

	private static Application instance;
	private Map<String, Object> mStaticInstances = new HashMap<String, Object>();

	/*package*/ Config mConfig;
	/*package*/ IUser<?> mUser;
	/*package*/ IUserConfig<?> mUserConfig;
	/*package*/ boolean mHasLogout = false;
	/*package*/ Runnable mLoginedRun;

	private boolean mFirstLaunch;

	public static final <A extends AbsApp> A get() {
		return (A)instance;
	}

	public AbsApp() {
		instance = this;
	}

	public boolean isFirstLaunch() {
		return mFirstLaunch;
	}

	public boolean isExited() {
		return isActivitieStackEmpty();
	}

	public void cacheSingleInstance(Object obj) {
		mStaticInstances.put(obj.getClass().getName(), obj);
	}

	public <O> O getSingleInstance(Class<O> clazz) {
		return (O)mStaticInstances.get(clazz.getName());
	}

	public void removeSingleInstance(Class<?> clazz) {
		mStaticInstances.remove(clazz.getName());
	}

	@Override
	public void onCreate() {
		super.onCreate();
		if(getConfig() == null) throw new NullPointerException("getConfig() 返回值不能为null。请不要返回Config.get()");

		ensureInfos();
	}

	protected abstract Config getConfig();

	private void ensureInfos() {
		mFirstLaunch = SharedPrefHelper.AppS.getFirstLaunch(this);
		if(mFirstLaunch) SharedPrefHelper.AppS.clearFirstLaunch(this);
	}

	/*package*/ void onActivityCreate(AbsActivity acty) {
		mActivitieStack.push(new WeakReference<AbsActivity>(acty));
	}

	/*package*/ void onActivityDestroy(AbsActivity acty) {
		AbsActivity refActy;
		for (WeakReference<? extends AbsActivity> actyRef : mActivitieStack) {
			refActy = actyRef.get();
			if (refActy == null || refActy == acty) {
				mActivitieStack.remove(actyRef);
			}
		}
		if (mFirstLaunch && isExited()) {
			mFirstLaunch = false;
		}
	}

	private boolean isActivitieStackEmpty() {
		for (WeakReference<? extends AbsActivity> actyRef : mActivitieStack) {
			if (actyRef.get() == null) mActivitieStack.remove(actyRef);
		}
		return mActivitieStack.isEmpty();
	}

	/**由于无论是进入新的Activity还是返回到旧的Activity，将要显示的页面B总是先创建，将要放入后台或销毁的页面A
	 * 总是在B.onCreate()之后执行A.onDestroy()或直接被系统回收，因此只要有Activity还要显示，本变量的元素个数总大于0，
	 * 即<h1>mActivities.size()在App退出之前总是大于0。</h1><br/>
	 * 这里关于退出的定义：
	 * 认为只要有Activity在显示，就表示没有退出；当没有要显示的了，则表示App退出了。
	 * 关于没有要显示的了，是在返回栈里面没有Activity了，正在显示的Activity-->finish()-->onDestroy()了。
	 * 此时可能有人有个问题：返回栈里面的Activity由于资源不足被系统销毁了，是怎么处理的呢？
	 * 销毁时返回栈里的记录仍然存在，只是内存里的实例对象被销毁，同时本变量会自动丢掉一个key，size()减少，
	 * 但是当返回时，会根据返回栈记录重建Activity，本变量会增加记录，并且在执行返回操作的A.onDestroy()之前。
	 **/
	//private WeakHashMap<AbsActivity, Object> mActivities = new WeakHashMap<AbsActivity, Object>();
	private Stack<WeakReference<? extends AbsActivity>> mActivitieStack = new Stack<WeakReference<? extends AbsActivity>>();
}
